<template>
  <div>
    <!-- <div>
      浏览器录音听写：<button id="btn_control" @click="btnControl">{{ buttonText }}</button>
    </div>
    <div id="result">{{ resultText }}</div> -->
  </div>
</template>

<script>
import CryptoJS from 'crypto-js'
import { Base64 } from 'js-base64'
const APPID = 'fe9e9d4f'
const API_SECRET = 'MGFjODUzNjU0YzdkNjM0YjZkZGZlMzU5'
const API_KEY = '926514dd4007649016764a87bb8d09c1'
const RecorderManager = require('../../../public/recorder.umd')
const recorder = new RecorderManager('./plugins2')
let countdownInterval
let iatWS
export default {
  components: {},
  props: {},
  data() {
    return {
      buttonText: '开始录音',
      resultText: '',
      resultTextTemp: '',
      btnStatus: 'UNDEFINED', // "UNDEFINED" "CONNECTING" "OPEN" "CLOSING" "CLOSED"
    }
  },
  computed: {},
  watch: {},
  methods: {
    btnControl() {
      if (this.btnStatus === 'UNDEFINED' || this.btnStatus === 'CLOSED') {
        this.connectWebSocket()
      } else if (this.btnStatus === 'CONNECTING' || this.btnStatus === 'OPEN') {
        // 结束录音
        recorder.stop()
      }
    },
    getWebSocketUrl() {
      // 请求地址根据语种不同变化
      var url = 'wss://iat-api.xfyun.cn/v2/iat'
      var host = 'iat-api.xfyun.cn'
      var apiKey = API_KEY
      var apiSecret = API_SECRET
      var date = new Date().toGMTString()
      var algorithm = 'hmac-sha256'
      var headers = 'host date request-line'
      var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v2/iat HTTP/1.1`
      var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret)
      var signature = CryptoJS.enc.Base64.stringify(signatureSha)
      var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`
      var authorization = btoa(authorizationOrigin)
      url = `${url}?authorization=${authorization}&date=${date}&host=${host}`
      return url
    },

    toBase64(buffer) {
      var binary = ''
      var bytes = new Uint8Array(buffer)
      var len = bytes.byteLength
      for (var i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i])
      }
      return window.btoa(binary)
    },

    countdown() {
      let seconds = 60
      this.buttonText = `录音中（${seconds}s）`
      countdownInterval = setInterval(() => {
        seconds = seconds - 1
        if (seconds <= 0) {
          clearInterval(countdownInterval)
          recorder.stop()
        } else {
          this.buttonText = `录音中（${seconds}s）`
        }
      }, 1000)
    },

    changeBtnStatus(status) {
      this.btnStatus = status
      if (status === 'CONNECTING') {
        this.buttonText = '建立连接中'
        this.resultText = ''
        this.resultTextTemp = ''
      } else if (status === 'OPEN') {
        this.countdown()
      } else if (status === 'CLOSING') {
        this.buttonText = '关闭连接中'
      } else if (status === 'CLOSED') {
        this.buttonText = '开始录音'
      }
    },

    renderResult(resultData) {
      // 识别结束
      let jsonData = JSON.parse(resultData)
      if (jsonData.data && jsonData.data.result) {
        let data = jsonData.data.result
        let str = ''
        let ws = data.ws
        for (let i = 0; i < ws.length; i++) {
          str = str + ws[i].cw[0].w
        }
        // 开启wpgs会有此字段(前提：在控制台开通动态修正功能)
        // 取值为 "apd"时表示该片结果是追加到前面的最终结果；取值为"rpl" 时表示替换前面的部分结果，替换范围为rg字段
        if (data.pgs) {
          if (data.pgs === 'apd') {
            // 将resultTextTemp同步给resultText
            this.resultText = this.resultTextTemp
          }
          // 将结果存储在resultTextTemp中
          this.resultTextTemp = this.resultText + str
        } else {
          this.resultText = this.resultText + str
        }
        if (this.resultText) {
          this.$emit('voiceEnd', this.resultText)
        }
      }
      if (jsonData.code === 0 && jsonData.data.status === 2) {
        iatWS.close()
      }
      if (jsonData.code !== 0) {
        iatWS.close()
        console.error(jsonData)
      }
    },

    connectWebSocket() {
      const websocketUrl = this.getWebSocketUrl()
      if ('WebSocket' in window) {
        iatWS = new WebSocket(websocketUrl)
      } else if ('MozWebSocket' in window) {
        iatWS = new MozWebSocket(websocketUrl)
      } else {
        alert('浏览器不支持WebSocket')
        return
      }
      this.changeBtnStatus('CONNECTING')
      iatWS.onopen = e => {
        // 开始录音
        recorder.start({
          sampleRate: 16000,
          frameSize: 1280,
        })
        var params = {
          common: {
            app_id: APPID,
          },
          business: {
            language: 'zh_cn',
            domain: 'iat',
            accent: 'mandarin',
            vad_eos: 5000,
            dwa: 'wpgs',
          },
          data: {
            status: 0,
            format: 'audio/L16;rate=16000',
            encoding: 'raw',
          },
        }
        iatWS.send(JSON.stringify(params))
      }
      iatWS.onmessage = e => {
        this.renderResult(e.data)
      }
      iatWS.onerror = e => {
        recorder.stop()
        this.changeBtnStatus('CLOSED')
      }
      iatWS.onclose = e => {
        recorder.stop()
        this.changeBtnStatus('CLOSED')
      }
    },
  },
  created() {},
  mounted() {
    recorder.onStart = () => {
      this.changeBtnStatus('OPEN')
    }
    recorder.onFrameRecorded = ({ isLastFrame, frameBuffer }) => {
      if (iatWS.readyState === iatWS.OPEN) {
        iatWS.send(
          JSON.stringify({
            data: {
              status: isLastFrame ? 2 : 1,
              format: 'audio/L16;rate=16000',
              encoding: 'raw',
              audio: this.toBase64(frameBuffer),
            },
          })
        )
        if (isLastFrame) {
          this.changeBtnStatus('CLOSING')
        }
      }
    }
    recorder.onStop = () => {
      clearInterval(countdownInterval)
    }
  },
  beforeDestroy() {
    // 结束录音
    recorder.stop()
  },
}
</script>
<style scoped></style>
